package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 自定义漆面，实现公共字段自动填充处理逻辑
 */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    /**
     * 切入点
     */
    @Pointcut ("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill ) ")
    //注意com和前面的*要有空格
    public void autoFillPointCut(){

    }

    /**
     * 前置通知，在通知进行公共字段的赋值
     */
    @Before("autoFillPointCut()")
    public void autoFill(JoinPoint joinPoint ) throws Exception {
        log.info("开始进行公共字段的自动填充...");

        //获取到当前被拦截的方法上的数据库操作类型
        MethodSignature signature =(MethodSignature)joinPoint.getSignature() ;
        //获得方法上的注解对象
        AutoFill autoFill =signature .getMethod() .getAnnotation(AutoFill.class );
        OperationType operationType =autoFill .value() ;


        //方法签名对象
        //获取到当前被拦截的方法上的参数-实体对象
        Object[] args=joinPoint .getArgs();
        if(args==null||args.length ==0){
            return;
        }

        Object entity=args[0] ;

        //准备赋值的对象
        LocalDateTime now=LocalDateTime.now() ;
        Long currentId= BaseContext.getCurrentId() ;

        //根据当前不同的操作类型，未对应的属性通过反射来赋值
        if(operationType ==OperationType.INSERT){
            Method setCreateTime=entity.getClass() .getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME,LocalDateTime.class );
            Method setUpdateTime=entity.getClass() .getDeclaredMethod(AutoFillConstant .SET_UPDATE_TIME,LocalDateTime.class );
            Method setCreateUser=entity.getClass() .getDeclaredMethod(AutoFillConstant .SET_CREATE_USER,Long.class );
            Method setUpdateUser=entity.getClass() .getDeclaredMethod(AutoFillConstant .SET_UPDATE_USER ,Long.class );
            //通过反射为对象的属性赋值
            setCreateTime.invoke(entity,now) ;
            setUpdateTime.invoke(entity,now) ;
            setCreateUser.invoke(entity,currentId) ;
            setUpdateUser  .invoke(entity,currentId);
        }else if(operationType ==OperationType.UPDATE){
            Method setUpdateTime=entity.getClass() .getDeclaredMethod(AutoFillConstant .SET_UPDATE_TIME,LocalDateTime.class );
            Method setUpdateUser=entity.getClass() .getDeclaredMethod(AutoFillConstant .SET_UPDATE_USER,Long.class );
            //通过反射为对象的属性赋值
            setUpdateTime.invoke(entity,now) ;
            setUpdateUser  .invoke(entity,currentId);
        }

    }
}
